#ifndef COROUTINE_IO_MANAGER_H
#define COROUTINE_IO_MANAGER_H

#include "TimerManager.hpp"
#include "Scheduler.hpp"
#include "Fiber.hpp"
#include "Channel.hpp"
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <sys/epoll.h>
#include <unordered_map>

namespace DBServer {
namespace coroutine
{

/// @brief IO事件
enum class IOEvent { 
    NONE    = 0b0000,       // 无事件
    READ    = EPOLLIN,      // 读事件EPOLLIN
    WRITE   = EPOLLOUT,     // 写事件EPOLLOUT
    HUP     = EPOLLHUP      // 异常事件EPOLLDUP
};

using io_ev_t = std::uint32_t;

class IOManager : public Scheduler, public TimerManager {
public:
    using ptr = std::shared_ptr<IOManager>;

private:
    /// @brief 每一个fd的IO事件上下文
    struct IOContext {

        /// @brief 事件上下文
        struct EventContext {
            // 事件执行的调度器
            Scheduler *scher = nullptr;
            // 事件协程
            Fiber::ptr fiber;
            // 事件回调函数
            std::function<void()> cb;
        };

        /// @brief 获取事件的上下文
        EventContext& get_ctx(IOEvent ev);

        /// @brief 重置事件上下文
        void reset_ctx(EventContext &ctx);

        /// @brief 触发事件
        void trigger_ev(IOEvent ev);

        EventContext read;                      // 读事件的上下文
        EventContext write;                     // 写事件的上下文
        EventContext hup;                       // 异常事件的上下文
        int fd = 0;                             // 事件关联的fd
        io_ev_t events = 0;               // 当前的事件
        std::mutex mtx;
    };

public:

    /// @brief 构造函数
    /// @param threads  线程数量
    /// @param caller   是否将调用线程包含进去
    /// @param name     调度器的名称
    IOManager(std::size_t threads = 1, bool caller = true, const std::string& name = "");

    /// @brief 析构函数
    ~IOManager();

    /// @brief 添加事件
    int add_ev(int fd, IOEvent ev, std::function<void()> cb = nullptr);

    /// @brief 删除事件
    /// 不会触事件
    bool del_ev(int fd, IOEvent ev);

    /// @brief 取消事件
    /// 会触发事件
    bool cancel_ev(int fd, IOEvent ev);

    /// @brief 取消所有事件
    bool cancel_all(int fd);

    /// @brief 返回当前的IOManager
    static IOManager* GetThis();
protected:
    void tickle() override;
    bool stopping() override;
    void idle() override;
    void on_timer_insert_at_front() override;

    /// @brief 判断是否可以停止
    bool stopping(std::uint64_t& timeout);

private:
    int epfd = 0;                                           // epoll fd 
    Channel chan;                                           // 协程之间通信的组件
    std::atomic<std::size_t> pending_ev_count = {0};        // 当前等待执行的事件数量
    std::shared_mutex io_mgr_mtx;
    std::unordered_map<int, IOContext *> io_ctxs;           // io事件的上下文
};

}   // coroutine   
}   // DBServer

#endif // !COROUTINE_IO_MANAGER_H